package org.springblade.modules.ad.service.impl;

import com.google.common.collect.Lists;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springblade.core.tool.utils.CollectionUtil;
import org.springblade.modules.ad.entity.AdGroup;
import org.springblade.modules.ad.entity.AdOU;
import org.springblade.modules.ad.service.AdGroupService;
import org.springblade.modules.ad.service.AdOUService;
import org.springblade.modules.ad.service.AdUserService;
import org.springblade.modules.ad.utils.LdapUtil;
import org.springblade.modules.ad.utils.Result;
import org.springframework.ldap.core.LdapTemplate;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.naming.directory.Attributes;
import javax.naming.directory.BasicAttribute;
import javax.naming.directory.BasicAttributes;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.CountDownLatch;

import static org.springblade.modules.ad.utils.LdapUtil.buildDn;

/**
 * ou 操作类
 * @ClassName ADOUServiceImpl.java
 * @version 1.0.0
 * @author zhangyunjiao
 * @createTime 2021/8/27
 */
@Service
public class AdOUServiceImpl implements AdOUService {

	private final Logger logger = LoggerFactory.getLogger(getClass());


	@Resource
	private LdapTemplate ldapTemplate;
	@Resource
	private ThreadPoolTaskExecutor executor;
	@Resource
	private AdGroupService adGroupService;
	@Resource
	private AdUserService adUserService;

	@Override
	public Result addOU(AdOU ouObject) {
		List<String> errObj = addOUObject(ouObject, Lists.newArrayList());
		if (CollectionUtil.isNotEmpty(errObj)) {
			return Result.of().error(errObj);
		}else{
			return Result.of().success();
		}
	}


	/**
	 * 添加OU 层级方法
	 * @param ouObject
	 */
	private List<String> addOUObject(AdOU ouObject,List<String> errOU){
		// TODO 待添加 引入quart 创建定时任务同步钉钉架构数据
		try {
			// 添加OU
			addOUMethod(ouObject);
			// 添加域组
			addAdGroupMethod(ouObject);
		} catch (Exception e) {
			// TODO 代写一个通用的LDAP 的异常解析方法或类
			// e.printStackTrace();
			logger.error("OU:【"+ouObject.getName()+"】路径:【"+ouObject.getBasePath()+"】添加失败，错误原因："+e.getMessage());
			// 记录添加失败的任务
			errOU.add(ouObject.getName());
			return errOU;
		}
		if (CollectionUtil.isNotEmpty(ouObject.getChildren())){
			// 线程池处理
			for (AdOU ouChildren:ouObject.getChildren()){
				// TODO 线程池需进一步优化
				// System.out.println("主线程 name -->" + Thread.currentThread().getName() + "start");
				 executor.execute(() -> addOUObject(ouChildren,errOU));
			}
		}
		return errOU;
	}

	/**
	 * 添加OU
	 * @param ouObject
	 */
	private void addOUMethod(AdOU ouObject) {
		Attributes attrs = new BasicAttributes();
		BasicAttribute ocAttr = new BasicAttribute("objectClass");
		ocAttr.add("top");
		ocAttr.add("organizationalUnit");
		attrs.put(ocAttr);
		attrs.put("ou", ouObject.getName());
		attrs.put("description", ouObject.getDescription());
		// 添加 OU
		ldapTemplate.bind(buildDn(ouObject.getBasePath(), ouObject.getName(), LdapUtil.AD_DN_TYPE_OU), null, attrs);
	}


	/**
	 * 添加域组
	 * @param ouObject
	 */
	private void addAdGroupMethod(AdOU ouObject) {
		LinkedList<String> basePath = Lists.newLinkedList();
		if (null != ouObject.getBasePath()) {
			basePath.addAll(ouObject.getBasePath());
		}
		basePath.add(ouObject.getName());
		ouObject.setBasePath(basePath);
		// 添加域组
		adGroupService.addAdGroup(ouObject);
	}
}
